package main;

import java.io.File;
import java.util.Map;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.*;

/**
 * 
 * Parser. Reads the xml-input, creates the graph representation. ThreadUnsafe.
 * 
 */
public class Parser extends DefaultHandler {

	/**
	 * graph
	 */
	Map<Integer, Node> graph = null;
	String tagName = "";
	int capacity;
	int id;
	int srcid;
	int dstid;

	/**
	 * Creates a new instance of the parser.
	 */
	public Parser() {
		tagName = "";
	}

	/**
	 * gets the graph
	 * 
	 * @return
	 */
	public Map<Integer, Node> getGraph() {
		return graph;
	}

	/**
	 * Parses a given file and stores the graph in a graph structure.
	 * 
	 * @param filename
	 *            file to parse.
	 * @param graph
	 *            graph representation.
	 * @return true, if no error.
	 */
	public boolean parseFile(String filename, Map<Integer, Node> graph) {

		File file = new File(filename);
		if (file.canRead()) {
			try {

				this.graph = graph;

				SAXParserFactory factory = SAXParserFactory.newInstance();
				SAXParser parser;
				parser = factory.newSAXParser();

				parser.parse(file, this);

				return true;
			} catch (Exception ex) {
				Console.printlnWithForce(ex.getLocalizedMessage());
				return false;
			}
		} else {

			Console.printlnWithForce("File not found or cannot be read!");
			return false;
		}
	}

	@Override
	public void startDocument() throws SAXException {
		TimeTest.start("parser");
	}

	@Override
	public void endDocument() throws SAXException {
		TimeTest.stop();
	}

	@Override
	public void startElement(String uri, String localName, String qName,
			Attributes attributes) throws SAXException {
		tagName = qName;

	}

	@Override
	public void endElement(String uri, String localName, String qName)
			throws SAXException {

		if (qName.equals("node")) {

			if (graph.containsKey(id)) {
				graph.get(id).setCapacity(capacity);
			} else {
				Node node = new Node(id, capacity);
				graph.put(id, node);
			}

		} else if (qName.equals("edge")) {
			if (!graph.containsKey(srcid)) {
				graph.put(srcid, new Node(srcid, 0));
			}
			if (!graph.containsKey(dstid)) {
				graph.put(dstid, new Node(dstid, 0));
			}

			graph.get(srcid).addPostNode(graph.get(dstid));
			graph.get(dstid).addPredNode(graph.get(srcid));
		} else {
			tagName = "";
		}
	}

	@Override
	public void characters(char[] ch, int start, int length)
			throws SAXException {

		if (tagName.equals("id")) {
			id = new Integer(new String(ch, start, length).trim());
		} else if (tagName.equals("capacity")) {
			capacity = new Integer(new String(ch, start, length).trim());
		} else if (tagName.equals("srcid")) {
			srcid = new Integer(new String(ch, start, length).trim());
		} else if (tagName.equals("dstid")) {
			dstid = new Integer(new String(ch, start, length).trim());
		}
	}

	// this is called when document is not valid:
	@Override
	public void error(SAXParseException ex) throws SAXException {
		Console.printlnWithForce("ERROR: [at " + ex.getLineNumber() + "] " + ex);
	}

	// this is called when document is not well-formed:
	@Override
	public void fatalError(SAXParseException ex) throws SAXException {
		Console.printlnWithForce("FATAL_ERROR: [at " + ex.getLineNumber()
				+ "] " + ex);
	}

	@Override
	public void warning(SAXParseException ex) throws SAXException {
		Console.printlnWithForce("WARNING: [at " + ex.getLineNumber() + "] "
				+ ex);
	}

}
